#include<vector>
#include<string>
#include<semaphore.h>
using namespace std;
#define SIZE 10
class Task
{
public:
    Task()
    {
        ;
    }
    Task(int x,int y,char op)
    :_x(x)
    ,_y(y)
    ,_op(op)
    {
        ;
    }
    void operator()()
    {
        switch(_op)
        {
            case '+':
            {
                _result = _x + _y;
                _exitcode = 0;
            }
            break;
            case '-':
            {
                _result = _x - _y;
                _exitcode = 0;
            }
            break;
            case '*':
            {
                _result = _x * _y;
                _exitcode = 0;
            }
            break;
            case '/':
            {
                if(_y == 0)
                    _exitcode = 1;
                else 
                _result = _x / _y;
            }
                break;
             case '%':
            {   
                if(_y == 0)
                    _exitcode = 1;
                else    
                _result = _x % _y;
            }
            break;
        }
    }
    string getformat()
    {
        return  to_string(_x) + _op + to_string(_y)+'?';
    }
    string getRformat()
    {
        return to_string(_result) + "("+to_string(_exitcode) + ")";
    }
    int _x;
    int _y;
    char _op;
    int _result;
    int _exitcode = 0;
};
template<class T>
class CirQueue
{
public:
    CirQueue(int n = SIZE)
    :vt_(n)
    ,head_(0)
    ,tail_(0)
    {
        sem_init(&Consumer_,0,0);
        sem_init(&Productor_,0,n);
        pthread_mutex_init(&Con_mutex,nullptr);
        pthread_mutex_init(&Pro_mutex,nullptr);
    }
    ~CirQueue()
    {
        sem_destroy(&Consumer_);
        sem_destroy(&Productor_);
        pthread_mutex_destroy(&Con_mutex);
        pthread_mutex_destroy(&Pro_mutex);
    }
     void Lock(pthread_mutex_t& mutex)
    {
        pthread_mutex_lock(&mutex);
    }
    void Unlock(pthread_mutex_t& mutex)
    {
        pthread_mutex_unlock(&mutex);
    }
    void push(const T& data)
    {
        sem_wait(&Productor_);//申请信号量
        tail_ = tail_ % vt_.size();
        Lock(Con_mutex);//加锁
        vt_[tail_++] = data;
        Unlock(Con_mutex);//解锁
        sem_post(&Consumer_);//释放信号量
    }
    void pop(T& data)
    {
        sem_wait(&Consumer_);
        head_ = head_ % vt_.size();
        Lock(Pro_mutex);
        data = vt_[head_++];//多线程访问会出问题,这里还要加锁,因为信号量只是起到限制执行流数量
        Unlock(Pro_mutex);
        sem_post(&Productor_);
    }
public:
    std::vector<T> vt_;
    int head_;
    int tail_;
    sem_t Consumer_;
    sem_t Productor_;
    pthread_mutex_t Con_mutex;
    pthread_mutex_t Pro_mutex;
};